package com.central.apps.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.central.app.common.cache.CfgRedisCache;
import com.central.app.common.constant.ShowTypeEnum;
import com.central.app.common.util.AppCommonUtil;
import com.central.app.dao.CommonDao;
import com.central.app.entity.*;
import com.central.app.model.BizApp;
import com.central.app.model.BizAttribute;
import com.central.app.model.BizObject;
import com.central.app.model.CommonModel;
import com.central.app.service.HandlerService;
import com.central.apps.common.constant.BizConstant;
import com.central.apps.entity.*;
import com.central.apps.service.BudgetTempleteService;
import com.central.common.exception.business.BusinessException;
import com.central.common.util.ToolUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 预算模版接口实现类
 *
 * @author 李大超
 * @date 2023/3/23
 */
@Slf4j
@Service
public class BudgetTempleteServiceImpl implements BudgetTempleteService {

    @Autowired
    private CfgRedisCache cfgRedisCache;
    @Autowired
    private CommonDao commonDao;
    @Autowired
    private HandlerService handlerService;

    /**
     * 组织字段和数据信息
     *
     * @param app
     * @param params
     * @return Map < String, Object>
     */
    @Override
    public Map<String, Object> combineData(String app, Map<String, Object> params) throws Exception {
        String tempName = MapUtils.getString(params, "tempName");
        params.remove("tempName");

        // 查询预算模版配置信息
        List<Map<String, Object>> list = commonDao.findBySql("select id, temptable from gq_budgettempcfg where tempname = '" + tempName + "'");

        if (CollectionUtils.isEmpty(list)) {
            throw new BusinessException("未维护预算模版配置信息!");
        }

        Map<String, Object> map = list.get(0);
        Integer id = MapUtils.getInteger(map, "id");
        String tempTable = MapUtils.getString(map, "temptable");

        // 查询预算模版字段明细信息
        list = commonDao.findBySql("select * from gq_budgettempfields where pkeyid = " + id + " order by sort");

        if (CollectionUtils.isEmpty(list)) {
            throw new BusinessException("未维护预算模版字段明细信息!");
        }

        // 组织字段信息数据
        Map<String, Object> resMap = new HashMap<>();
        List<Map<String, Object>> fieldsList = new ArrayList<>();
        for (Map<String, Object> fieldMap : list) {
            Map<String, Object> tempMap = convertJson(fieldMap);
            fieldsList.add(tempMap);
        }
        resMap.put("columns", fieldsList);

        // 获取对象信息
        BizObject bizObject = cfgRedisCache.getCacheObject(tempTable);
        // 获取应用信息
        BizApp bizApp = cfgRedisCache.getCacheApp(app);
        // 组织查询模型
        CommonModel commonModel = combineModel(bizObject, bizApp, params);
        // 查询树形父级数据
        List<Map<String, Object>> dataList = commonDao.findList(commonModel);

        // 组织业务数据
        List<Map<String, Object>> tempList = convertData(dataList, list);
        resMap.put("data", tempList);

        // 组织分页总数
        resMap.put("count", dataList.size());

        return resMap;
    }

    /**
     *
     *
     * @param fieldMap
     * @return
     */
    private Map<String, Object> convertJson(Map<String, Object> fieldMap) {
        String fieldName = MapUtils.getString(fieldMap, BizConstant.FIELD_NAME);
        String showDesc = MapUtils.getString(fieldMap, BizConstant.SHOW_DESC);
        String showType = MapUtils.getString(fieldMap, BizConstant.SHOW_TYPE);
        String cfgJson = MapUtils.getString(fieldMap, BizConstant.CFG_JSON);

        FormAttribute formAttribute = new FormAttribute();
        formAttribute.setType(ShowTypeEnum.getShowTypeEnum(showType).getCode());
        formAttribute.setName(showDesc);
        formAttribute.setModel(fieldName);

        if (StringUtils.isNotEmpty(cfgJson)) {
            //转化请求的 json 数据
            JSONObject jsonObj = JSONObject.parseObject(cfgJson);
            //获取options对象
            JSONObject optionsObj = jsonObj.getJSONObject("options");

            // 组织选项
            FormOptions formOptions = new FormOptions();
            combineOptions(showType, optionsObj, formOptions);

            if (formOptions != null) {
                formAttribute.setOptions(formOptions);
            }

            //获取rules数组
            JSONArray rulesArray = jsonObj.getJSONArray("rules");
            if (rulesArray != null) {
                List<FormRule> formRules = combineRules(rulesArray);
                formAttribute.setRules(formRules);
            }
        } else {
            // 组织选项
            FormOptions formOptions = new FormOptions();
            combineOptions(showType, null, formOptions);

            if (formOptions != null) {
                formAttribute.setOptions(formOptions);

                List<FormRule> formRules = new ArrayList<>();
                formAttribute.setRules(formRules);
            }
        }

        return JSON.parseObject(JSON.toJSONString(formAttribute), Map.class);
    }

    /**
     * 插入预算预制信息
     *
     * @param tempName
     * @param pbiId
     * @param params
     */
    @Override
    public void addPrependData(String tempName, Integer pbiId, Map<String, Object> params) throws Exception {
        // 查询预添加的明细项
        List<Map<String, Object>> list = commonDao.findBySql("select * from gq_probugdetcfg where parentid = " + pbiId);

        if (CollectionUtils.isEmpty(list)) {
            return;
        }

        // 查询模版信息
        List<Map<String, Object>> tempList = commonDao.findBySql("select * from gq_budgettempcfg where tempname = '" + tempName + "'");

        if (CollectionUtils.isEmpty(tempList)) {
            throw new BusinessException("未配置预算模版信息!");
        }
        Map<String, Object> tempMap = tempList.get(0);
        Integer id = MapUtils.getInteger(tempMap, "id");
        String targetTable = MapUtils.getString(tempMap, "targettable");

        List<Map<String, Object>> tempDtlList = commonDao.findBySql("select sourcefield, targetfield from gq_budgettempdtlcfg where pkeyid = " + id);

        if (CollectionUtils.isEmpty(tempDtlList)) {
            return;
        }

        // 组织并插入模版数据
        for (Map<String, Object> map : list) {
            Map<String, Object> addMap = new HashMap<>();
            addMap.put(BizConstant.PB_ID, params.get(BizConstant.PB_ID));
            addMap.put(BizConstant.PB_YEAR, params.get(BizConstant.PB_YEAR));
            addMap.put(BizConstant.PRO_ID, params.get(BizConstant.PRO_ID));
            addMap.put(BizConstant.SUBJECT_NO, params.get(BizConstant.SUBJECT_NO));
            addMap.put(BizConstant.PBI_PARENT_ID, params.get(BizConstant.PBI_ID));
            addMap.put(BizConstant.PBI_PARENT_DESC, params.get(BizConstant.PBI_DESC));

            // 遍历模版配置明细并组织插入信息
            for (Map<String, Object> tempDtlMap : tempDtlList) {
                addMap.put(MapUtils.getString(tempDtlMap,"targetfield"), map.get(tempDtlMap.get("sourcefield")));
            }

            handlerService.insert(targetTable, addMap);
        }
    }

    /**
     * 组织选项数据
     *
     * @param showType
     * @param optionsObj
     * @param formOptions
     */
    private void combineOptions(String showType, JSONObject optionsObj, FormOptions formOptions) {
        ShowTypeEnum showTypeEnum = ShowTypeEnum.getShowTypeEnum(showType);

        if (optionsObj != null) {
            formOptions.setDefaultValue(optionsObj.getString("defaultValue"));
            formOptions.setRequired(optionsObj.getBoolean("required") == null ? false : optionsObj.getBoolean("required"));
            formOptions.setDisabled(optionsObj.getBoolean("disabled") == null ? false : optionsObj.getBoolean("disabled"));
            formOptions.setHideCondition(optionsObj.getString("hideCondition"));
            formOptions.setDisabledCondition(optionsObj.getString("disabledCondition"));
            formOptions.setRequireCondition(optionsObj.getString("requireCondition"));
            formOptions.setIsCustomizedprocessing(optionsObj.getBoolean("isCustomizedprocessing") == null ? false : optionsObj.getBoolean("isCustomizedprocessing"));
            formOptions.setCustomizedprocessingevent(optionsObj.getString("customizedprocessingevent"));
            switch (showTypeEnum) {
                case POPUP:
                    throw new BusinessException("暂未实现弹出框配置!");
                case SELECT:
                    Integer remote = optionsObj.getInteger("remote");
                    formOptions.setRemote(remote);
                    if (remote > 1) {
                        FormRemoteData remoteData = new FormRemoteData();
                        //获取Remote Data对象
                        JSONObject remoteDataObj = optionsObj.getJSONObject("remoteData");

                        if (remoteDataObj == null) {
                            throw new BusinessException("预算字段下拉框远端数据未维护信息!");
                        }

                        remoteData.setUrl(remoteDataObj.getString("url"));
                        remoteData.setMethods(remoteDataObj.getString("methods"));
                        remoteData.setLabel(remoteDataObj.getString("label"));
                        remoteData.setValue(remoteDataObj.getString("value"));

                        //获取Remote options list对象
                        JSONArray remoteOptionsArray = remoteDataObj.getJSONArray("list");

                        if (remoteOptionsArray != null) {
                            List<FormSearchOptions> searchOptions = new ArrayList<>();
                            for (int i = 1; i < remoteOptionsArray.size(); i++) {
                                //获取option对象
                                JSONObject optionObj = remoteOptionsArray.getJSONObject(i);

                                FormSearchOptions remoteOptions = new FormSearchOptions();
                                remoteOptions.setKey(optionObj.getString("key"));
                                remoteOptions.setValue(optionObj.getString("value"));
                                remoteOptions.setFixedValue(optionObj.getBoolean("isFixedValue"));

                                searchOptions.add(remoteOptions);
                            }
                            remoteData.setOptions(searchOptions);
                        }

                        formOptions.setRemoteData(remoteData);
                    } else {
                        formOptions.setDictionaryCode(optionsObj.getString("dictionaryCode"));
                    }
                    break;
                case NUMBER:
                    formOptions.setCalculaterule(optionsObj.getString("calculaterule"));
                    formOptions.setPrecision(optionsObj.getString("precision") == null ? "2" : optionsObj.getString("precision"));
                    formOptions.setMin("0");
                    break;
                case TEXTAREA:
                default:
                    break;
            }
        } else {
            switch (showTypeEnum) {
                case POPUP:
                    throw new BusinessException("预算字段信息下拉框必须配置属性");
                case SELECT:
                    throw new BusinessException("预算字段信息下拉框必须配置属性");
                case NUMBER:
                    formOptions.setDefaultValue("0");
                    formOptions.setRequired(false);
                    formOptions.setDisabled(false);
                    formOptions.setHideCondition("");
                    formOptions.setDisabledCondition("");
                    formOptions.setRequireCondition("");
                    formOptions.setCalculaterule("");
                    formOptions.setPrecision("2");
                    formOptions.setMin("0");
                    break;
                case TEXTAREA:
                default:
                    formOptions.setDefaultValue("");
                    formOptions.setRequired(false);
                    formOptions.setDisabled(false);
                    formOptions.setHideCondition("");
                    formOptions.setDisabledCondition("");
                    formOptions.setRequireCondition("");
                    break;
            }
        }
    }

    /**
     * 组织规则数据
     *
     * @param rulesArray
     */
    private List<FormRule> combineRules(JSONArray rulesArray) {
        List<FormRule> formRules = new ArrayList<>();
        if (rulesArray != null) {
            for (int i = 1; i < rulesArray.size(); i++) {
                //获取option对象
                JSONObject ruleObj = rulesArray.getJSONObject(i);

                FormRule formRule = new FormRule();
                formRule.setType(ruleObj.getString("type"));
                formRule.setMessage(ruleObj.getString("message"));

                formRules.add(formRule);
            }

            return formRules;
        }

        return formRules;
    }

    /**
     * 组织结果数据
     *
     * @param dataList
     * @param fieldsList
     */
    private List<Map<String, Object>> convertData(List<Map<String, Object>> dataList, List<Map<String, Object>> fieldsList) {
        List<Map<String, Object>> list = new ArrayList<>();
        for (Map<String, Object> dataMap : dataList) {
            Map<String, Object> tempMap = new HashMap<>();
            tempMap.put(BizConstant.BIZ_ID, dataMap.get(BizConstant.BIZ_ID));
            tempMap.put(BizConstant.PB_ID, dataMap.get(BizConstant.PB_ID));
            tempMap.put(BizConstant.PKEY_ID, dataMap.get(BizConstant.PKEY_ID));
            tempMap.put(BizConstant.PRO_ID, dataMap.get(BizConstant.PRO_ID));
            tempMap.put(BizConstant.SUBJECT_NO, dataMap.get(BizConstant.SUBJECT_NO));
            tempMap.put(BizConstant.PBI_ID, dataMap.get(BizConstant.PBI_ID));
            tempMap.put(BizConstant.PBI_DESC, dataMap.get(BizConstant.PBI_DESC));

            for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
                for (Map<String, Object> fieldsMap : fieldsList) {
                    if (entry.getKey().equals(fieldsMap.get(BizConstant.FIELD_NAME))) {
                        tempMap.put(entry.getKey(), entry.getValue());
                        break;
                    }
                }
            }

            list.add(tempMap);
        }

        return list;
    }

    /**
     * 组织查询模型
     *
     * @param bizObject
     * @param bizApp
     * @param params
     * @return CommonModel
     * @throws Exception
     */
    private CommonModel combineModel(BizObject bizObject, BizApp bizApp, Map<String, Object> params) throws Exception {
        CommonModel commonModel = new CommonModel();

        // 组织全部字段信息
        List<BizAttribute> bizAttributes = bizObject.getAttributes();
        StringBuilder fieldStr = new StringBuilder();
        if (CollectionUtils.isNotEmpty(bizAttributes)) {
            for (BizAttribute bizAttribute : bizAttributes) {
                fieldStr.append(bizAttribute.getColumnname()).append(",");
            }
        } else {
            // 查询字段信息
            List<Map<String, Object>> fieldList = commonDao.findBySql("select * from biz_attribute where object_id = " + bizObject.getId());

            for (Map<String, Object> fieldMap : fieldList) {
                fieldStr.append(fieldMap.get("columnname")).append(",");
            }
        }

        if (StringUtils.isNotEmpty(fieldStr.toString())) {
            fieldStr.deleteCharAt(fieldStr.length() - 1);
            params.put("selectcolumns", fieldStr.toString());
        }

        AppCommonUtil.setFindParams(commonModel, params, bizApp, bizObject);

        Map<String,Object> wheresMap = commonModel.getWhereEqs();
        if(ToolUtil.isNotEmpty(wheresMap)){
            for(Map.Entry<String, Object> entry : wheresMap.entrySet()){
                if(StringUtils.isEmpty(entry.getValue().toString())){
                    wheresMap.remove(entry.getValue());
                }
            }
        }

        return commonModel;
    }
}
